"""
类别特征编码及检测处理偏态分布
"""
import pandas as pd
import numpy as np
from sklearn.preprocessing import OneHotEncoder

from sklearn.feature_selection import RFECV
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import StratifiedKFold

# 特征处理和转换
from sklearn.preprocessing import LabelEncoder, StandardScaler, MinMaxScaler
from imblearn.over_sampling import SMOTE


def fit_transform_features(df):
    # 1. 类别特征编码
    def encode_categorical(df):
        # 无序特征用独热编码
        nominal_features = ['BusinessTravel','Department','EducationField','JobRole','MaritalStatus','OverTime']
        encoder = OneHotEncoder(handle_unknown='ignore', sparse_output=False)
        # 新版本的写法
        encoded = encoder.fit_transform(df[nominal_features])
        encoded_df = pd.DataFrame(encoded, columns=encoder.get_feature_names_out(nominal_features), index=df.index)
        df = df.drop(nominal_features, axis=1)
        df = pd.concat([df, encoded_df], axis=1)
        return df, encoder

    # 2. 检测和处理偏态分布
    def handle_skewness(df):
        numeric_cols = df.select_dtypes(include=['float64', 'int64']).columns
        skewed_features = []
        for col in numeric_cols:
            skewness = df[col].skew()
            if abs(skewness) > 0.5:  # 设定偏态阈值
                df[col] = np.log1p(df[col])
                skewed_features.append(col)
        print(f"进行对数变换的特征: {skewed_features}")
        return df, skewed_features

    # 编码类别特征
    df, encoder = encode_categorical(df)
    # 处理偏态分布
    df, skewed_features = handle_skewness(df)
    return df, encoder, skewed_features

def transform_features(df, encoder, skewed_features):
    # 编码类别特征
    nominal_features = ['BusinessTravel','Department','EducationField','JobRole','MaritalStatus','OverTime']
    encoded = encoder.transform(df[nominal_features])
    encoded_df = pd.DataFrame(encoded, columns=encoder.get_feature_names_out(nominal_features), index=df.index)
    df = df.drop(nominal_features, axis=1)
    df = pd.concat([df, encoded_df], axis=1)
    # 处理偏态分布
    for col in skewed_features:
        df[col] = np.log1p(df[col])
    return df

"""
标准化
"""
def fit_scale_features(df):
    numeric_cols = df.select_dtypes(include=['float64', 'int64']).columns
    scaler = StandardScaler()
    df[numeric_cols] = scaler.fit_transform(df[numeric_cols])
    return df, scaler, numeric_cols

def scale_features(df, scaler, numeric_cols):
    df[numeric_cols] = scaler.transform(df[numeric_cols])
    return df

"""
smote处理样本不均匀
"""
def handle_imbalance(X, y):
    smote = SMOTE(random_state=42)
    X_balanced, y_balanced = smote.fit_resample(X, y)
    return X_balanced, y_balanced

"""
特征选择
"""
def select_features_cv(X, y, step=1, cv=5):
    estimator = LogisticRegression(max_iter=1000, random_state=42)
    rfecv = RFECV(
        estimator=estimator,
        step=step,
        cv=StratifiedKFold(cv),
        scoring='accuracy',
        n_jobs=-1
    )
    X_selected = rfecv.fit_transform(X, y)
    print(X_selected)
    selected_features = X.columns[rfecv.support_]
    return X_selected, selected_features, rfecv
